﻿using AbpDemo.Admins.Dto;
using AbpDemo.Admins;
using AbpDemo.Roles.Dto;
using AbpDemo.Utility;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using System.Linq.Expressions;
using AbpDemo.RoleMenus;
using Microsoft.AspNetCore.Http;
using AbpDemo.Menus;
using AbpDemo.Filters;

namespace AbpDemo.Roles
{
    [ApiExplorerSettings(GroupName = "v1")]
    public class RoleService : CrudAppExtService<Role, RoleDto, Guid, CreateUpdateRoleDto>, IRoleService
    {
        private readonly IRepository<Role, Guid> repository;
        private readonly IRepository<RoleMenu, Guid> repositoryRoleMenus;
        private readonly IRepository<Menu, Guid> repositoryMenus;
        private readonly IHttpContextAccessor httpContext;

        public RoleService(
            IRepository<Role, Guid> repository, 
            IRepository<RoleMenu, Guid> repositoryRoleMenus,
            IRepository<Menu, Guid> repositoryMenus,
            IHttpContextAccessor httpContext
            ) : base(repository)
        {
            this.repository = repository;
            this.repositoryRoleMenus = repositoryRoleMenus;
            this.repositoryMenus = repositoryMenus;
            this.httpContext = httpContext;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="createInput"></param>
        /// <returns></returns>
        [HttpPost("/Role/Create")]
        [CustomerAuthorizationFilter("system:role:create")]
        public override async Task<ResultDto<RoleDto>> CreateAsync(CreateUpdateRoleDto createInput)
        {
            var roleCode = await repository.FindAsync(m => m.RoleCode == createInput.RoleCode);
            if (roleCode != null)
            {
                return new ResultDto<RoleDto> { Code = ResultState.Failed, Message = "角色编码重复" };
            }
            var roleName = await repository.FindAsync(m => m.RoleName == createInput.RoleName);
            if (roleName != null)
            {
                return new ResultDto<RoleDto> { Code = ResultState.Failed, Message = "角色名称重复" };
            }
            return await base.CreateAsync(createInput);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="createInput"></param>
        /// <returns></returns>
        [HttpPost("/Role/Update")]
        [CustomerAuthorizationFilter("system:role:edit")]
        public override async Task<ResultDto<RoleDto>> UpdateAsync(Guid Id, CreateUpdateRoleDto createInput)
        {
            var roleCode = await repository.FindAsync(m => m.RoleCode == createInput.RoleCode && m.Id != Id);
            if (roleCode != null)
            {
                return new ResultDto<RoleDto> { Code = ResultState.Failed, Message = "角色编码重复" };
            }
            var roleName = await repository.FindAsync(m => m.RoleName == createInput.RoleName && m.Id != Id);
            if (roleName != null)
            {
                return new ResultDto<RoleDto> { Code = ResultState.Failed, Message = "角色名称重复" };
            }
            return await base.UpdateAsync(Id, createInput);
        }

        /// <summary>
        /// 获取全部角色
        /// </summary>
        /// <returns></returns>
        [HttpGet("/role/queryall")]
        [CustomerAuthorizationFilter("system:user:create", "system:user:edit")]
        public async Task<ResultDto<List<RoleDto>>> QueryAllAsync()
        {
            var role = (await repository.GetQueryableAsync())
                .Select(m => new RoleDto {
                    Id = m.Id,
                    RoleName = m.RoleName
                }).ToList();
            return new ResultDto<List<RoleDto>> { Code = ResultState.Success, Data = role };
        }


        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="queryDto"></param>
        /// <returns></returns>
        [HttpGet("/Role/Page")]
        [CustomerAuthorizationFilter("system:role:page")]
        public async Task<ResultDto<PagedResultDto<RoleDto>>> GetPageAsync([FromQuery] Dto.QueryDto queryDto)
        {
            List<(bool, Expression<Func<Role, bool>>)> condition = new List<(bool, Expression<Func<Role, bool>>)>
            {
                (!string.IsNullOrEmpty(queryDto.RoleName),m=>m.RoleName.Contains(queryDto.RoleName)),
                (!string.IsNullOrEmpty(queryDto.RoleCode),m=>m.RoleCode.Contains(queryDto.RoleCode))
            };

            return await BaseGetPageAsync(condition, queryDto);
        }

        /// <summary>
        /// 重写删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpGet("/Role/Delete")]
        [CustomerAuthorizationFilter("system:role:delete")]
        public override async Task<ResultDto<bool>> DeleteAsync(Guid Id)
        {
            await repositoryRoleMenus.DeleteAsync(m=>m.RoleId == Id);
            return await base.DeleteAsync(Id);
        }

        /// <summary>
        /// 获取当前用户具有的权限Id
        /// </summary>
        /// <returns></returns>
        [HttpGet("/Role/GetTreeIds")]
        [CustomerAuthorizationFilter("system:role:setPermission")]
        public async Task<ResultDto<List<Guid>>> GetTreeIds(Guid RoleId)
        {
            var nodeids = (from rolemenu in await repositoryRoleMenus.GetQueryableAsync()
                          join menu in await repositoryMenus.GetQueryableAsync()
                          on rolemenu.MenuId equals menu.Id
                          where rolemenu.RoleId == RoleId && menu.MenuType == Menus.Enums.MenuType.Button
                          select menu.Id).ToList();
                          

            return new ResultDto<List<Guid>> {  Code = ResultState.Success, Data = nodeids };
        }

        /// <summary>
        /// 设置权限
        /// </summary>
        /// <param name="RoleId"></param>
        /// <param name="MenuIds"></param>
        /// <returns></returns>
        [HttpPost("/Role/SetPermission")]
        [CustomerAuthorizationFilter("system:role:setPermission")]
        public async Task<ResultDto<bool>> SetPermission(Guid RoleId, List<Guid> MenuIds)
        {
            try
            {
                //删除原有中间表数据
                await repositoryRoleMenus.DeleteAsync(m => m.RoleId == RoleId);

                var list = MenuIds.Select(m => new RoleMenu
                {
                    RoleId = RoleId,
                    MenuId = m
                });

                await repositoryRoleMenus.InsertManyAsync(list);
                return new ResultDto<bool> { Code = ResultState.Success, Data = true, Message = "设置权限成功" };
            }
            catch (Exception e)
            {
                return new ResultDto<bool> { Code = ResultState.Success, Message = e.Message };
            }
        }

        /// <summary>
        /// 暂时未用到，由前端通过父子组件传值获取当前行数据
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [CustomerAuthorizationFilter("system:role:edit")]
        public override Task<ResultDto<RoleDto>> GetAsync(Guid Id)
        {
            return base.GetAsync(Id);
        }
    }
}
